using System;
using System.Collections.Generic;
using System.Linq;
using DDA;
using Sirenix.Utilities;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;
using YDExtendTool.Scripts;

namespace YDExtendTool.Editor.TreeDataCreator
{
    public class TreeView : GraphView
    {
        public new class UxmlFactory : UxmlFactory<TreeView, UxmlTraits>{}
        public TreeNodeView RootView;
        public TreeView()
        {
            Insert(0,new GridBackground());
            this.AddManipulator(new ContentZoomer());
            this.AddManipulator(new ContentDragger());
            this.AddManipulator(new SelectionDragger());
            this.AddManipulator(new RectangleSelector());
            
            var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/YDExtendTool/Editor/TreeDataCreator/TreeDataCreator.uss");
            styleSheets.Add(styleSheet);

            GraphViewMenu();

            graphViewChanged += OnGraphViewChange;
            
            RegisterCallback<MouseEnterEvent>(MouseEnterControl);
        }
        
        private void MouseEnterControl(MouseEnterEvent evt)
        {
           TreeDataCreator.instance.Inspector.UpdateViewData();
        }
        private GraphViewChange OnGraphViewChange(GraphViewChange gvc)
        {
            
            // 连线
            if (gvc.edgesToCreate != null)
            {
                gvc.edgesToCreate.ForEach(e =>
                {
                    if (e.output.node is TreeNodeView outputNode && e.input.node is TreeNodeView inputNode)
                    {
                        switch (outputNode.NodeData)
                        {
                            case TreeNodeMultipleNextBase stNodeSelectBase:
                                stNodeSelectBase.ChildNodes.Add(inputNode.NodeData);
                                stNodeSelectBase.OnConnected(inputNode.NodeData);
                                break;
                        }
                    }
                });
            }
            
            // 删除线
            if (gvc.elementsToRemove != null)
            {
                gvc.elementsToRemove.ForEach(elm =>
                {
                    if (elm is Edge e)
                    {
                        TreeNodeView outputNode = e.output.node as TreeNodeView;
                        TreeNodeView inputNode = e.input.node as TreeNodeView;
                        if (outputNode != null && inputNode != null)
                        {
                            switch (outputNode.NodeData)
                            {
                                case TreeNodeMultipleNextBase stNodeSelectBase:
                                    for(int i=0;i<stNodeSelectBase.ChildNodes.Count;i++)
                                    {
                                        var value = stNodeSelectBase.ChildNodes[i];
                                        if (value.Guid == inputNode.NodeData.Guid)
                                        {
                                            stNodeSelectBase.ChildNodes.Remove(value);
                                            break;
                                        }
                                    }
                                    break;
                            }
                        }
                    }
                });
            }

            return gvc;
        }
        public void CreateNode(Type type, Vector2 position)
        {
            if (Activator.CreateInstance(type) is TreeNodeBase treeNodeBase)
            {
                // treeNodeBase.NodeName = type.Name;
                treeNodeBase.Init();
                TreeNodeView node = new TreeNodeView(treeNodeBase);
                node.SetPosition(new Rect(position, Vector2.one));
                this.AddElement(node);
                
                // 添加到容器中
                TreeDataCreator.instance.VisitNodes.Add(node.NodeData.Guid,node);
            }
        }
        
        // 筛选能连接的点
        public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter)
        {
            return ports.Where((endPorts) =>
            {

                if (startPort.node is TreeNodeView startPortNode && endPorts.node is TreeNodeView endPortsNode)
                {
                    var result = endPorts.direction != startPort.direction
                                 && endPorts.node != startPort.node
                                 && startPortNode.NodeData.TreeNodeBaseType == endPortsNode.NodeData.TreeNodeBaseType;
                    if (startPortNode.NodeData is DDATreeNodeBase ddaTreeNodeBase && endPortsNode.NodeData is DDATreeNodeBase end)
                    {
                        result &= ddaTreeNodeBase.CanConnect(end);
                    }

                    return result;
                }
                return false;
            }).ToList();
        }
        

        public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
        {
            base.BuildContextualMenu(evt);
            evt.menu.AppendAction("刷新",FlushView);
        }

        public void FlushView(DropdownMenuAction obj)
        {
            FlushView();
        }

        public void FlushView()
        {
            TreeDataCreator.instance.VisitNodes.ForEach((pair =>
            {
                pair.Value?.FlushView();
            }));
        }

        public void GraphViewMenu()
        {
            var menuWindowProvider = ScriptableObject.CreateInstance<TreeDataCreator.RightClickMenu>();
            menuWindowProvider.OnSelectEntryHandle = OnMenuSelectEntry;

            nodeCreationRequest += context =>
            {
                SearchWindow.Open(new SearchWindowContext(context.screenMousePosition), menuWindowProvider);
            };
        }
        private bool OnMenuSelectEntry(SearchTreeEntry searchtreeentry, SearchWindowContext context)
        {
            var windowRoot = TreeDataCreator.instance.rootVisualElement;
            var windowMousePosition = windowRoot.ChangeCoordinatesTo(windowRoot.parent,
                context.screenMousePosition - TreeDataCreator.instance.position.position);
            var graphMousePosition =contentViewContainer.WorldToLocal(windowMousePosition);
            CreateNode((Type)searchtreeentry.userData,graphMousePosition);
            return true;
        }
    }
}

